package www.wen.com.common.lib.data.db

import android.util.Log
import com.google.gson.Gson
import com.orhanobut.logger.Logger
import kotlinx.coroutines.*
import www.wen.com.common.lib.data.db.database.AppDatabase
import www.wen.com.common.lib.data.entities.*
import www.wen.com.common.lib.data.entities.builtIn.Cache
import www.wen.com.common.lib.data.entities.builtIn.Result
import www.wen.com.common.lib.util.RoomManagerUtil
import javax.inject.Inject
import javax.inject.Singleton

/**
 * @author WEN
 * @Description:
 * @date 2020/11/25 11:03
 */
@Singleton
class AppDbHelperImpl @Inject constructor(appDatabase: AppDatabase) : AppDbHelper {

    private var mAppDatabase: AppDatabase = appDatabase

    override suspend fun <T> insertCache(key: String, cacheEntity: T): Boolean {
        var isInsertSuccess = false
        Log.d("Beni", "dbHelper insertCache: $key cacheEntity = $cacheEntity")
        GlobalScope.launch(Dispatchers.IO) {
            mAppDatabase.getCacheDao().insert(Cache(key, RoomManagerUtil.toByteArray(cacheEntity)))
            isInsertSuccess = true
        }
        return isInsertSuccess
    }

    override suspend fun <T> findByKey(key: String): T? {
        return withContext(Dispatchers.IO) {
            val cache = mAppDatabase.getCacheDao().findByKey(key)
            cache?.run {
                return@withContext RoomManagerUtil.toObject(cache.data) as T
            }
        }
    }

    override suspend fun <T> queryCache(
        key: String,
        error: Result.Error,
        successBlock: (suspend (CoroutineScope, T) -> Unit),
        errorBlock: (suspend (CoroutineScope, Result.Error) -> Unit),
    ) {
        withContext(Dispatchers.IO) {
            val cacheData = mAppDatabase.getCacheDao().findByKey(key)
            Log.d("Beni", "dbHelper queryCache: $key cacheEntity = $cacheData")
            if (cacheData != null) {
                try {
                    Logger.i("key = $key ,Data = ${Gson().toJson(RoomManagerUtil.toObject(cacheData.data))}")
                    successBlock.invoke(this, RoomManagerUtil.toObject(cacheData.data) as T)
                } catch (e: Exception) {
                    errorBlock.invoke(this, Result.Error(e))
                }
            } else {
                errorBlock.invoke(this, error)
            }
        }
    }



}